#include "StdAfx.h"
#include "TimeLine.h"

#include <iostream>
#include <QTextStream>
#include <QMap>
#include <QFile>
#include "TimeLineImp.h"
#include "utils.h"

TimeLine::TimeLine( void ):imp(new TimeLineImp())
{

} 

void TimeLine::AddEvent( CMFT mft,TimeEvent e )
{
	events.insert(e,mft);
}


void TimeLine::TimeBasedInference( QTreeWidgetItem *nxt, CMFT* cur,SYSTEMTIME startTime,SYSTEMTIME endTime) 
{	
	using namespace std;
	if (!cur->haveTimes()) {
		cout<<"MFT HAVE NO TIME AT "<<cur->diskOffSet<<endl;
		return;
	}
	NTFSFileTime stamps = cur->getTimes();
	QString ext = cur->getFileNameExtension();
	//check time range and early return
	if (!imp->InRange(stamps,startTime,endTime)) {
		return;
	}
	StdInfoTime SI = stamps.stdInfoTime;
	FileNameTime FN = stamps.fileNameTime;
	QString ops="";
	bool isDir = cur->isDirectory();
	//
	//big table inference
	if (isDir)
		goto LabelDIR;//check DIR instead
	//![1.new]
	if (AllEquel(SI)&&AllEquel(FN) && FN.creation==SI.creation) {
		AddEvent(*cur,TimeEvent(SI.creation,"new"));
	}
	//![new]
	//![2.rename|3.IntraMove]
	if (SI.creation==FN.creation&&SI.modify==FN.modify&&SI.access==FN.access && SI.entry>FN.entry)
		AddEvent(*cur,TimeEvent(SI.entry,"Rename|IntraMove"));
	//![ rename|intramove]
	//![4.interMove]
	if(ext=="exe") {//<executable
		//FI.MEA and SI.EA equal and FI.C==SN.C < other and	SI.M < other
		if (FN.modify==FN.entry && FN.entry==FN.access && FN.access==SI.entry && SI.entry==SI.access&&
			FN.creation==SI.creation && FN.creation<FN.modify && SI.modify<FN.modify) {
				AddEvent(*cur,TimeEvent(SI.access,"InterMove"));
		}
	} else {//non-executable
		if (AllEquel(FN)&& SI.access==FN.access &&SI.entry==FN.entry &&SI.creation<FN.creation && SI.modify <FN.modify) {
			AddEvent(*cur,TimeEvent(SI.access,"InterMove"));
		}
	}
	//![ 4.interMove]
	//![5 Copy]
	if(ext=="exe") {//<executable
		if (AllEquel(FN)&&SI.entry==FN.entry && SI.access==FN.access &&SI.entry==FN.entry&& 
			SI.creation ==FN.creation && FN.modify > SI.modify) {
				AddEvent(*cur,TimeEvent(SI.access,"Copy"));
		}
	} else {//non-executable
		if (AllEquel(FN) && SI.access==FN.access &&
			SI.creation ==FN.creation && FN.modify > SI.modify && FN.entry==SI.entry) {
				AddEvent(*cur,TimeEvent(SI.access,"Copy"));
		}
	}
	//![ 5 copy]
	//![6 Modify content]
	if(ext!="doc"){//normal file
		if (SI.modify==SI.entry && SI.entry>SI.creation && SI.entry>SI.access &&
			SI.entry>FN.modify&&SI.entry>FN.access&&SI.entry>FN.creation&&SI.entry>FN.entry) 
			AddEvent(*cur,TimeEvent(SI.modify,"Modify Content"));
	}else {//office file
		if (SI.modify==SI.entry && SI.entry==SI.access&& SI.entry>SI.creation &&
			FN.modify==FN.entry && FN.entry==FN.access&& FN.entry>FN.creation && FN.modify==SI.modify)
			AddEvent(*cur,TimeEvent(SI.modify,"Modify Content"));
	}
	//![ 6 Modify content]
	//![7 modify general attribute]
	if (SI.entry>SI.modify&&SI.entry>SI.access&&SI.entry>SI.creation&&
		SI.entry>FN.modify&&SI.entry>FN.access&&SI.entry>FN.creation&&SI.entry>FN.entry)
		AddEvent(*cur,TimeEvent(SI.entry,"Modify general attr."));
	//![7]
	//![8 modify summary attr.]
	if(SI.modify==SI.entry && SI.modify>SI.access && SI.modify>SI.creation &&
		SI.entry>FN.modify&&SI.entry>FN.access&&SI.entry>FN.creation&&SI.entry>FN.entry)
		AddEvent(*cur,TimeEvent(SI.modify,"Modify summary attr."));
	//![ 8]
	//![9 intra-replace]
	//TODO:infer intra replace
	//![9]
	//![10 inter replace]
	//TODO:inter replace
	//![10]
	//![ 11 touch]
	if (ext=="exe") {
		if (SI.entry>SI.modify&&SI.entry>SI.access&&SI.entry>SI.creation&&
			SI.entry>FN.modify&&SI.entry>FN.access&&SI.entry>FN.creation&&SI.entry>FN.entry) {
				AddEvent(*cur,TimeEvent(SI.entry,"touch."));
		}
	}
	//![ 11]
	goto LabelDIREND;

LabelDIR:
	//![1new]
	if (AllEquel(FN)&&AllEquel(SI)&&FN.entry==SI.entry) {
		AddEvent(*cur,TimeEvent(SI.entry,"New"));
	}
	//![1]
	//![2rename]
	if (cur->getFileName()=="newfolder.renagain")
		int a=100;
	if(SI.entry>SI.modify&&SI.entry>SI.access&&SI.entry>SI.creation&&
		SI.entry>FN.modify&&SI.entry>FN.access&&SI.entry>FN.creation&&SI.entry>FN.entry &&//SI.E is newest
		SI.creation==FN.creation&&SI.modify==FN.modify&&SI.access==FN.access)
		AddEvent(*cur,TimeEvent(SI.entry,"Rename"));
	//![2]
	
LabelDIREND:
	/*
	//
	//good old check
	if (AllEquel(FN))
	if (!cur->isDirectory()) {
	//CMFT *par = cur->getParent();
	//AllTypes
	if (SI.creation<FN.creation && 
	AllEquel(FN)) {
	ops+= "FN.CisInterMoveTime&NoRenOrMoveInCurVol()";
	AddEvent(*cur,TimeEvent(FN.creation,"Inter Volume Move"));
	//AddEvent(*cur,TimeEvent(SYSTEMTIME(),"NoRenOrMoveInCurVol"));
	}
	if (!AllEquel(FN)) {
	if (SI.creation<FN.creation && SI.entry>FN.entry) {
	ops+="Replaced&CTime>OriginFileCtime()";
	AddEvent(*cur,TimeEvent(SYSTEMTIME(),"Replaced&CTime>OriginFileCtime()"));
	}
	if(SI.creation==FN.creation) {
	ops+="FNisFromSIBefore(LastRen|IntraMove)";
	AddEvent(*cur,TimeEvent(SYSTEMTIME(),"FNisFromSIBefore(LastRen|IntraMove)"));
	}
	}
	if(SI.creation>SI.modify) {
	ops+="NoMInCurVolumn()";
	}
	if (SI.creation==SI.modify) {
	ops+="NoMSinceCreation()";
	}
	if(SI.creation<SI.modify) {
	ops+="$SI.MIsMTimeInCurVolumn";
	AddEvent(*cur,TimeEvent(SI.modify,"Content modify"));
	}


	//Files Except exe and Office
	if (ext!="exe"&&ext!="doc") {
	if (SI.creation>SI.modify && SI.creation>SI.entry) {
	ops+="CopyFromOtherVolWithSI.M&SI.E()";
	}
	}
	//Office files
	if (ext=="doc") {
	if(FN.modify==FN.access && FN.access==FN.entry && FN.entry>SI.creation) {
	ops+="FN.MIsMInCurVol()";
	AddEvent(*cur,TimeEvent(FN.modify,"content modify"));
	if(SI.entry==FN.modify) {
	ops+="NoRenOrIntraMoveAfterFN.M()";
	}
	}
	if (SI.entry>SI.modify) {
	ops+="SI.EIs{Ren,IntraMove,M)";
	AddEvent(*cur,TimeEvent(SI.entry,"rename|intra volume move|content modify"));
	}
	if (!(SI.modify==FN.modify)) {
	ops+="Tamper()";
	}
	if (SI.modify==SI.entry && SI.entry>=SI.access &&SI.access>=SI.creation ) {
	ops+="SI.MisM";
	AddEvent(*cur,TimeEvent(SI.modify,"content Modify"));
	}
	}
	if (ext=="exe") {
	if (SI.entry>=SI.access && SI.entry>=SI.creation && SI.entry>=SI.modify &&
	SI.entry>=FN.access && SI.entry>=FN.creation && SI.entry>=FN.entry &&
	SI.entry>=FN.modify) {
	} else {
	ops+="tampered";
	}
	}
	}//!cur->isdirectory() 
	else  {
	//directory
	if (SI.modify==SI.access&&SI.access==SI.entry && SI.entry>SI.creation) {
	ops+="ContentChangeAtSI.E()";
	AddEvent(*cur,TimeEvent(SI.entry,"directory content change"));
	}
	}
	}*/
	//display
	QTreeWidgetItem* op = new QTreeWidgetItem();
	op->setData(0,Qt::DisplayRole,"Possible Ops:"+ops);
	if (ops!="")
		nxt->setBackgroundColor(0,QColor(255,0,0));
	nxt->addChild(op);
}

void TimeLine::clear()
{
	events.clear();
}

bool TimeLine::writeLog( QString logName )
{
	QFile logFile(logName);
	if (!logFile.open(QFile::WriteOnly)) {
		return false;
	}
	QTextStream os(&logFile);
	for(QMap<TimeEvent,CMFT>::iterator it = events.begin();it!=events.end();it++) {
		os<<ToString(&it.key()._sysTime)<<" "<<it.key()._msg<<it->getPath()<<it->getFileName();
		os<<endl;
	}
	return true;
}

namespace TL {
	enum _DISPCOL {
		COL_TIME=0,
		COL_OP,
		COL_FILEPATH,
		COL_DELETE
	};
}

void TimeLine::fillTree( QTreeWidget *tree )
{
	tree->clear();
	//tree->setSortingEnabled(true);
	tree->setHeaderLabels(QStringList()<<"Time"<<"Operation"<<"FileName"<<"IsDeleted");
	for(QMap<TimeEvent,CMFT>::iterator it = events.begin();it!=events.end();it++) {
		//fill
		QTreeWidgetItem *nxt = new QTreeWidgetItem();
		nxt->setData(TL::COL_TIME,Qt::DisplayRole,ToString(&it.key()._sysTime));
		nxt->setData(TL::COL_OP,Qt::DisplayRole,it.key()._msg);
		nxt->setData(TL::COL_FILEPATH,Qt::DisplayRole,it->getPath()+it->getFileName());
		nxt->setData(TL::COL_DELETE,Qt::DisplayRole,it->isDeleted());
		//add to tree
		tree->addTopLevelItem(nxt);
	}
}

